package com.qxy.practice.concurrent;

import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author : 戚欣扬
 * @code :
 */
public class ThreadTransmit {
    private int num = 0 ;
    private Lock lock = new ReentrantLock();
    Condition condition1 = lock.newCondition();
    Condition condition2 = lock.newCondition();
    Condition condition3 = lock.newCondition();
//    V1 使用公平锁 / 睡眠实现 1+ 1-
/*    private Lock lock = new ReentrantLock();



    public void increase(){
        lock.lock();
        try{
            num++;
            System.out.println(Thread.currentThread().getName()+"num ="+num);
        }finally {
            lock.unlock();
        }
    }

    public void decrease(){
        lock.lock();
        try{
            num--;
            System.out.println(Thread.currentThread().getName()+"num ="+num);
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadTransmit threadTransmit = new ThreadTransmit();

        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                threadTransmit.increase();
            },"A").start();


            new Thread(()->{
                threadTransmit.decrease();
            },"B").start();
        }

    }*/
//      V2 使用synchronized+wait+notify 实现 虚假唤醒问题 死锁问题
/*        public synchronized void increase(){
            //判断
            while(num!=0){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            //执行
            System.out.println(Thread.currentThread().getName()+":num = " + (++num));
            //通知
            this.notifyAll();
        }

    public synchronized void decrease(){
        //判断
        while(num!=1){
            try {
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        //执行
        System.out.println(Thread.currentThread().getName()+":num = " + (--num));
        //通知
        this.notifyAll();
    }

    public static void main(String[] args) {
        ThreadTransmit threadTransmit = new ThreadTransmit();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                threadTransmit.increase();
            }
        },"A").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                threadTransmit.decrease();
            }
        },"B").start();

        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                threadTransmit.increase();
            }
        },"C").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                threadTransmit.decrease();
            }
        },"D").start();

    }*/
//      v3      lock.lock() +condition.await() + condition.signalAll()
public  void increase(){
    lock.lock();
    try {
        //判断
        while(num!=0){
            try {
                condition1.await();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        //执行
        System.out.println(Thread.currentThread().getName()+":num = " + (++num));
        //通知
        condition1.signalAll();
    } finally {
        lock.unlock();
    }
}

    public  void decrease(){
        lock.lock();
        try {
            //判断
            while(num!=1){
                try {
                    condition1.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            //执行
            System.out.println(Thread.currentThread().getName()+":num = " + (--num));
            //通知
            condition1.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        ThreadTransmit threadTransmit = new ThreadTransmit();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                threadTransmit.increase();
            }
        },"A").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                threadTransmit.decrease();
            }
        },"B").start();

        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                threadTransmit.increase();
            }
        },"C").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                threadTransmit.decrease();
            }
        },"D").start();

    }
//      v4      A 5->B 10->C 15 loop 10

    // concurrentModifyException
}


